using System;
using System.Linq;
using System.Threading.Tasks;
using CodeAngel.Domain.Framework;

namespace CodeAngel.Domain.Aggregates
{
    /// <summary>
    /// Special aggregate to log in a user
    /// </summary>
	public partial class UserLogInAggregate : Aggregate
	{

		#region LoadAsync

        /// <summary>
        /// A special LoadAsync method for logging in a user.
        /// </summary>
		public Task LoadAsync(string userName, string password)
		{
            return Task.Factory.StartNew(() =>
            {
                string Filter = string.Format("SELECT UserID FROM [User] WHERE UserName = '{0}' AND Password = '{1}'", userName, password);
                var ThisServiceProxy = DomainDataServiceClient.Create();
                this.DtoHost = ThisServiceProxy.GetDtoHost(this.GetType().FullName, Filter, userName, password);
                this.BuildObjectGraph();
            });
		}

		#endregion

		#region Root

		public new User Root
		{
		    get
		    {
                return base.Root as User;
		    }
		}

		#endregion

		#region CreateNew

        /// <summary>
        /// Creates the root of this aggreate as a new entity.
        /// </summary>
        /// <remarks>
        /// The currently logged in user will be used for security purposes.
        /// </remarks>
		public void CreateNew()
		{
            this.CreateNew(User.LoggedInUser);
		}

        /// <summary>
        /// Creates the root of this aggreate as a new entity/collection.
        /// </summary>
		public void CreateNew(User user)
		{
            var ThisRoot = new User(this);
            this.User = user;
            ThisRoot.IsNew = true;
            ThisRoot.InitializeAllProperties();
            ThisRoot.SetDefaultPropertyValues();
            ThisRoot.BuildObjectGraphCompleted();
            this.DtoHost = new DtoHost();
            base.Root = ThisRoot;
		}

		#endregion

		#region LoadAsync

        /// <summary>
        /// Instructs this aggregate to asynchronously load its object graph based on the
        /// identified id.  The currently logged in user (see User.LoggedInUser) will be used for
        /// security related purposes.
        /// </summary>
		public Task LoadAsync(Guid id)
		{
            return this.LoadAsync(new UserFilter(id), User.LoggedInUser);
		}

		#endregion

		#region IsFilterTypeValid

        /// <summary>
        /// Determines if the passed in filter is valid for this aggregate.
        /// </summary>
		protected override bool IsFilterTypeValid(IFilter filter)
		{
            return (filter is UserFilter);
		}

		#endregion

		#region BuildObjectGraph

        /// <summary>
        /// Provides a way for the developer to custom build the object graph for this aggregate. 
        /// Be sure to set the _BuildObjectGraphIsHandled field to true to avoid having the
        /// auto-generated BuildObjectGraph code executed.
        /// </summary>
		partial void CustomBuildObjectGraph();

        /// <summary>
        /// Informs the auto-generated BuildObjectGraph method that building the object graph has
        /// already been handled and it does not need to do anything.
        /// </summary>
		private bool _BuildObjectGraphIsHandled = false;

        /// <summary>
        ///
        /// </summary>
		protected override void BuildObjectGraph()
		{
            // Offers the developer a way to build the object graph by hand.
            this.CustomBuildObjectGraph();
            if (this._BuildObjectGraphIsHandled) return;
            
            try
            {
            var ThisRoot = new User(this);
            var ThisUserDto = this.DtoHost.RootUsers[0];
            ThisRoot.InitializeAllScalarProperties(ThisUserDto);
            
            ThisRoot.InitializeUser_RolesProperty();
            foreach (var User_RoleDto19 in this.DtoHost.User_Roles.FindAll(ThisDto => ThisDto.UserID.Equals(ThisUserDto.ID)))
            {
            var User_Role19 = new User_Role(this);
            ThisRoot.User_Roles.Add(User_Role19);
            User_Role19.InitializeUserProperty(ThisRoot);
            User_Role19.InitializeUser_RoleIDProperty(User_RoleDto19.User_RoleID);
            
            var RoleDto20 = this.DtoHost.Roles.Find<RoleDto>(User_RoleDto19.RoleID);
            if (RoleDto20 != null)
            {
                var Role20 = new Role(this, User_Role19);
                User_Role19.InitializeRoleProperty(Role20);
            Role20.InitializeAllScalarProperties(RoleDto20);
            }
            else
            {
                User_Role19.InitializeRoleProperty();
            }
            }
            
            ThisRoot.InitializeUser_PermissionsProperty();
            foreach (var User_PermissionDto21 in this.DtoHost.User_Permissions.FindAll(ThisDto => ThisDto.UserID.Equals(ThisUserDto.ID)))
            {
            var User_Permission21 = new User_Permission(this);
            ThisRoot.User_Permissions.Add(User_Permission21);
            User_Permission21.InitializeUserProperty(ThisRoot);
            User_Permission21.InitializeUser_PermissionIDProperty(User_PermissionDto21.User_PermissionID);
            
            var PermissionDto22 = this.DtoHost.Permissions.Find<PermissionDto>(User_PermissionDto21.PermissionID);
            if (PermissionDto22 != null)
            {
                var Permission22 = new Permission(this, User_Permission21);
                User_Permission21.InitializePermissionProperty(Permission22);
            Permission22.InitializeAllScalarProperties(PermissionDto22);
            }
            else
            {
                User_Permission21.InitializePermissionProperty();
            }
            }
            
            ThisRoot.InitializeUser_DeniedPermissionsProperty();
            foreach (var User_DeniedPermissionDto23 in this.DtoHost.User_DeniedPermissions.FindAll(ThisDto => ThisDto.UserID.Equals(ThisUserDto.ID)))
            {
            var User_DeniedPermission23 = new User_DeniedPermission(this);
            ThisRoot.User_DeniedPermissions.Add(User_DeniedPermission23);
            User_DeniedPermission23.InitializeUserProperty(ThisRoot);
            User_DeniedPermission23.InitializeUser_DeniedPermissionIDProperty(User_DeniedPermissionDto23.User_DeniedPermissionID);
            
            var DeniedPermissionDto24 = this.DtoHost.Permissions.Find<PermissionDto>(User_DeniedPermissionDto23.DeniedPermissionID);
            if (DeniedPermissionDto24 != null)
            {
                var DeniedPermission24 = new Permission(this, User_DeniedPermission23);
                User_DeniedPermission23.InitializeDeniedPermissionProperty(DeniedPermission24);
            DeniedPermission24.InitializeAllScalarProperties(DeniedPermissionDto24);
            }
            else
            {
                User_DeniedPermission23.InitializeDeniedPermissionProperty();
            }
            }
            base.Root = ThisRoot;
            }
            catch (Exception ex)
            {
            throw new Exception("There was an unexpected problem building the object graph.  See inner exception for more info.", ex);
            }
		}

		#endregion

		#region SynchronizeDtos

        /// <summary>
        /// Provides a way for the developer to custom synchronize the dtos with the object graph
        /// for this aggregate.  Be sure to set the _SynchronizeDtosIsHandled field to true to
        /// avoid having the auto-generated synchronization code executed.
        /// </summary>
		partial void CustomSynchronizeDtos();

        /// <summary>
        /// Informs the auto-generated SynchronizeDtos method that synchronization has already been
        /// handled and it does not need to do anything.
        /// </summary>
		private bool _SynchronizeDtosIsHandled = false;

        /// <summary>
        ///
        /// </summary>
		protected override void SynchronizeDtos()
		{
            // Offers the developer a way to synchronize the dtos by hand.
            this.CustomSynchronizeDtos();
            if (this._SynchronizeDtosIsHandled) return;
            
            try
            {
            this.Root.SynchronizeDto(this.DtoHost.RootUsers);
            foreach (var User_Role25 in this.Root.User_Roles)
            {
                User_Role25.SynchronizeDto(this.DtoHost.User_Roles);
            var Role26 = User_Role25.Role;
            if (Role26 != null)
            {
                Role26.SynchronizeDto(this.DtoHost.Roles);
            }
            }
            foreach (var User_Permission27 in this.Root.User_Permissions)
            {
                User_Permission27.SynchronizeDto(this.DtoHost.User_Permissions);
            var Permission28 = User_Permission27.Permission;
            if (Permission28 != null)
            {
                Permission28.SynchronizeDto(this.DtoHost.Permissions);
            }
            }
            foreach (var User_DeniedPermission29 in this.Root.User_DeniedPermissions)
            {
                User_DeniedPermission29.SynchronizeDto(this.DtoHost.User_DeniedPermissions);
            var Permission30 = User_DeniedPermission29.DeniedPermission;
            if (Permission30 != null)
            {
                Permission30.SynchronizeDto(this.DtoHost.Permissions);
            }
            }
            }
                catch (Exception ex)
            {
                throw new Exception("There was an unexpected problem while synchronizing DTOs.  See inner exception for more info.", ex);
            }
		}

		#endregion

		#region UserHasPermissionToSave

        /// <summary>
        /// Identifies if the current user has permission to save all the updateable entities in
        /// this AggregateDefinition.
        /// </summary>
		protected override bool UserHasPermissionToSave()
		{
            return 
                this.User.CanUpdateUser_Role() &&
                this.User.CanUpdateUser_Permission() &&
                this.User.CanUpdateUser_DeniedPermission();
		}

		#endregion

	}
}

